package org.hackystat.devcathlon.ui.page.matches.manage.creatematchpanel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBoxMultipleChoice;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.hackystat.devcathlon.configuration.ConfigurationManager;
import org.hackystat.devcathlon.engine.event.Event;
import org.hackystat.devcathlon.engine.match.MatchManager;
import org.hackystat.devcathlon.engine.team.Team;
import org.hackystat.devcathlon.engine.team.TeamManager;
import org.hackystat.devcathlon.ui.DevcathlonSession;
import org.hackystat.devcathlon.ui.page.matches.manage.MatchesManagePage;
import org.hackystat.sensorbase.resource.projects.jaxb.Project;
import org.hackystat.utilities.tstamp.Tstamp;

/**
 * The stateless form for creating a new match.
 * @author robin
 *
 */
public class CreateMatchForm extends StatelessForm {
  /** Support serialization. */
  private static final long serialVersionUID = 1L;
  String matchStartTime = "";
  String startTimeInput = "";
  String endTimeInput = "";
  String matchName = "";
  String teamName = "";
  String opponentName = "";
  
  private List<Event> eventTypes = new ArrayList<Event>();
  Map<Team, Project> teams2projects = new HashMap<Team, Project>();
  
  /**
   * Creates the form.
   * @param id The component id.
   */
  public CreateMatchForm(String id) {
    super(id);
    setModel(new CompoundPropertyModel(this));
    add(new FeedbackPanel("feedback"));
    
    
    
    add(new FormComponentFeedbackBorder("matchStartTimeBorder")
    .add(new TextField("startTimeInput")
    .setRequired(true)
    .setLabel(new Model("Start Time"))));
    
    add(new FormComponentFeedbackBorder("matchEndTimeBorder")
    .add(new TextField("endTimeInput")
    .setRequired(true)
    .setLabel(new Model("End Time"))));
    
    add(new FormComponentFeedbackBorder("matchNameBorder")
    .add(new TextField("matchName")
    .setRequired(true)
    .setLabel(new Model("Match Name"))));
    
    add(new FormComponentFeedbackBorder("teamNameBorder")
    .add(new DropDownChoice("teamName", getUserTeamList())
    .setRequired(true)
    .setLabel(new Model("User's Team Name"))));
    
    add(new FormComponentFeedbackBorder("opponentNameBorder")
    .add(new DropDownChoice("opponentName", getOppTeamsList())
    .setRequired(true)
    .setLabel(new Model("Opponent Team Name"))));
    
    // Retrieve list of events.
    final List<String> eventLocations = ConfigurationManager.getInstance().getAllEventLocations();
    final List<String> eventNames = new ArrayList<String>();
    for (String eventLocation : eventLocations) {
      try {
        Event eClass = (Event) (Class.forName(eventLocation).newInstance());
        eventNames.add(eClass.getName());
      }
      catch (Exception e) {
        e.printStackTrace();
      }      
    }  
    
    // Add list of events to the form.
    final CheckBoxMultipleChoice checkEvents = new CheckBoxMultipleChoice("eventTypes", eventNames);
    
    add(new FormComponentFeedbackBorder("eventListBorder")
    .add(checkEvents
    .setRequired(true)
    .setLabel(new Model("Events"))));
      
    // Add button to the form.
    add(new Button("submitButton") {
      /** Support serialization */
      private static final long serialVersionUID = 1L;
      
      @Override
      public void onSubmit() {
        try {
          // Add events for the match.
          eventTypes.clear();
          
          for (String event : checkEvents.getInputAsArray()) {
            String eventLoc = eventLocations.get(Integer.valueOf(event));
            Event userSelect = (Event) (Class.forName(eventLoc).newInstance());
            eventTypes.add(userSelect);
          }
          
          // Set start and end date of the match.          
          XMLGregorianCalendar xmlStartTime = formatDate(startTimeInput);
          XMLGregorianCalendar xmlEndTime = formatDate(endTimeInput);

          // Set team and projects.  
          Team urs = TeamManager.getInstance().getTeam(teamName);
          Team opp = TeamManager.getInstance().getTeam(opponentName);  
          Project urProj = urs.getProject();
          Project oProj = opp.getProject();
          
          // Add team and project pair.
          teams2projects.put(urs, urProj);
          teams2projects.put(opp, oProj);
          // Add match.
         
          MatchManager.getInstance().addMatch(matchName, xmlStartTime, xmlEndTime, 
              teams2projects, eventTypes);
          MatchManager.getInstance().getMatch(matchName).acceptMatchInvitation(urs);
          setResponsePage(new MatchesManagePage());
        }
        catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }
  
  /**
   * The list of the user's opponents.
   * 
   * @return The list of opponents. 
   */
  private List<String> getOppTeamsList() {
    String email = DevcathlonSession.get().getEmail();   
    List<Team> teams = TeamManager.getInstance().getPossibleOpponent(email);
    
    List<String> opponentNames = new ArrayList<String>();
    for (int i = 0; i < teams.size(); i++) {
      opponentNames.add(teams.get(i).getName());
    }
    
    return opponentNames;
  }
  
  /**
   * The list of teams that the user is owner of.
   * 
   * @return The list of teams.
   */
  private List<String> getUserTeamList() {
    String email = DevcathlonSession.get().getEmail();
    List<Team> teams = TeamManager.getInstance().getOwnedTeams(email);
    
    List<String> teamNames = new ArrayList<String>();
    for (int i = 0; i < teams.size(); i++) {
      teamNames.add(teams.get(i).getName());
    }
    return teamNames;
  }

  /**
   * Reformats the start and end date input.
   * @param date The date input.
   * @return The new date format.
   */
  private XMLGregorianCalendar formatDate(String date) {
    XMLGregorianCalendar now = Tstamp.makeTimestamp();
    int year = Integer.parseInt(date.substring(6, 10));
    int month = Integer.parseInt(date.substring(0, 2));
    int day = Integer.parseInt(date.substring(3, 5));
    now.setMillisecond(1);
    now.setDay(day);
    now.setMonth(month);
    now.setYear(year);
    return now;
  }
  
  /**
   * Sets the start date.
   * @param start The start date.
   */
  public void setStartDate(String start) {
    this.startTimeInput = start;
  }
  
  /**
   * Gets the start date.
   * @return The start date.
   */
  public String getStartDate() {
    return this.startTimeInput;
  }
  
  /**
   * Sets the end date.
   * @param end The end date.
   */
  public void setEndDate(String end) {
    this.endTimeInput = end;
  }
  
  /**
   * Gets the end date.
   * @return The end date.
   */
  public String getEndDate() {
    return this.endTimeInput;
  }
  
  /**
   * Sets the match name.
   * @param name The match name.
   */
  public void setMatchName(String name) {
    this.matchName = name;
  }
  
  /**
   * Gets the match name.
   * @return The match name.
   */
  public String getMatchName() {
    return this.matchName;
  }
  
  /**
   * Sets the team name.
   * @param name The team name.
   */
  public void setTeamName(String name) {
    this.teamName = name;
  }
  
  /**
   * Sets the project name.
   * @param name The project name.
   */
  public void setProjectName(String name) {
    this.opponentName = name;
  }
  
  /**
   * Gets the team name.
   * @return The team name.
   */
  public String getTeamName() {
    return this.teamName;
  }
  
  /**
   * Gets the project name.
   * @return The project name.
   */
  public String getProjectName() {
    return this.opponentName;
  }
  
  /**
   * Sets the list of events selected.
   * @param event The list of events.
   */
  public void setEventTypes(List<Event> event) {
    this.eventTypes = event;
  }
  
  /**
   * Gets the list of events selected.
   * @return The list of events.
   */
  public List<Event> getEventTypes() {
    return this.eventTypes;
  }
}
